package server

import (
	"context"
	"errors"
	"fmt"
	global2 "longmen/server/config/global"
	"longmen/server/pkg/common/helper/const"
	time2 "longmen/server/pkg/common/helper/timehelper"
	"longmen/server/pkg/common/helper/util"
	"longmen/server/pkg/db/mysql/db_main"
	"longmen/server/pkg/db/mysql/models/models_main"
	pb "longmen/server/pkg/protobuf"
	"math/rand"
	"sync"
	"time"

	"github.com/fatih/structs"
	"github.com/spf13/cast"
	"gorm.io/gorm"
)

var lock sync.Mutex
var redisLock sync.Mutex

// 已抢到的红包信息队列
var diamondQueue = make(chan *models_main.Diamond, 2000)

/**
 * @Author admin
 * @Description //TODO 测试方法
 * @version: v1.8.0
 * @Date 17:42 2022/7/8
 * @Param
 * @return
 **/
func testUser() int {
	if result, err := global2.GetRds().LPop("TEST").Result(); err == nil {
		return cast.ToInt(result)
	}
	return 0
}

/**
 * @Author admin
 * @Description //TODO 测试方法
 * @version: v1.8.0
 * @Date 17:42 2022/7/8
 * @Param
 * @return
 **/
func pushUser() {
	//select GROUP_CONCAT(id) from(select id from db_user where id>6010810 LIMIT 50)tb1
	global2.GetRds().LPush("TEST", 6010811, 6010812, 6010813, 6010814, 6010815, 6010816, 6010817, 6010818, 6010819,
		6010820, 6010821, 6010822, 6010823, 6010824, 6010825, 6010826, 6010827, 6010828, 6010829, 6010830, 6010831, 6010832, 6010833,
		6010834, 6010835, 6010836, 6010837, 6010838, 6010839, 6010840, 6010841, 6010842, 6010843, 6010844, 6010845, 6010846, 6010847,
		6010848, 6010849, 6010850, 6010851, 6010852, 6010853, 6010854, 6010855, 6010856, 6010857, 6010858, 6010859, 6010860).Result()
}

/**
* @Author:admin
* @Description: 生成一条红包信息
* @Date: 11:24 2022/6/15
 */
func (s *Server) ProvideHongBao(ctx context.Context, provid *pb.ProvideHongBaoReq) (*pb.ProvideHongBaoResp, error) {
	//生成一个红包model
	hongBaoModel := generateHongBao(provid)
	//事务控制提交model到DB及缓存到redis中
	list := getRandomDiamondList(hongBaoModel)
	//恢复设置初始值
	hongBaoModel.SendDiamond = 0
	hongBaoModel.SendQuantity = 0
	//FIXME 测试使用
	//pushUser()
	//打乱顺序
	Shuffle(list)
	//生成每一红包保存到缓存，并且保存到数据库红包信息
	return hongBaoCommit(hongBaoModel, list)

}

/**
 * @Author admin
 * @Description //抢红包
 * @version: v1.8.0
 * @Date 18:14 2022/7/7
 * @Param
 * @return
 **/
func (s *Server) GrabHongBao(ctx context.Context, hongBaoReq *pb.GrabHongBaoReq) (*pb.GrabHongBaoResp, error) {
	session := global2.GetX().Begin()
	if err := db_main.DropDiamondTemp(session); err != nil {
		fmt.Println(err)
		session.Rollback()
	}
	/*---------======End of session=====----------*/
	hongBao, err := getOptimizedHongBao(hongBaoReq)
	if err != nil {
		return errMessage("未有此红包")
	}
	//领红包还示有开始
	if hongBao.StartTime > time.Now().Unix() {
		return errMessage("未有开始抢红包")
	}
	//领红包已结束
	//FIXME 测试语句
	//hongBaoReq.SenderUid = int64(testUser())

	if hongBao.EndTime < time.Now().Unix() || hongBao.TotalQuantity == hongBao.SendQuantity {
		return errMessage("红包已结束")
	}
	//进入抢红包的流程
	if diamond, err := evalScript(int(hongBaoReq.HongBaoId), int(hongBaoReq.UserId)); err == nil {
		switch diamond {
		case -1:
			return errMessage("红包已发完")
		case -2:
			return errMessage("用户不能重复抢红包")
		default:
			model := generateDiamondModel(diamond, hongBao.Id, hongBaoReq.UserId)
			//服务挂机,队列信息会丢的失
			//这里最好扔外部集群队列，然后再在队列中消费，通过WEBSOCKET 下推红包金额 从队列中批量取数据，批量入库，减少数据库压力
			diamondQueue <- model
			//
			return retMessage("抢红包成功", int32(model.GrabDiamond))
		}
	}
	return errMessage("抢红包失败")
}

/**
 * @Author admin
 * @Description lua 脚本 实现把用户加入并去重,并根据userid做为路由键,路由到不同的bucket 上面暂定有10桶，并且领取一个红包
 * @version: v1.8.0
 * @Date 18:07 2022/7/7
 * @Param
 * @return
 **/
func evalScript(hongBaoId, userId int) (int, error) {
	/*stringLua := `if (redis.call('SADD',KEYS[2],ARGV[1])>0) then
	   redis.call('EXPIRE',KEYS[2],ARGV[2])
	   local names={'TotalQuantity','SendQuantity'}
	   local bulk=redis.call('HMGET',KEYS[1],unpack(names))
	   if tonumber(bulk[1])>tonumber(bulk[2]) then
	      redis.call('HSET',KEYS[1],'SendQuantity',tonumber(bulk[2])+1)
	      return redis.call('LPOP',KEYS[3])
	   else
	      return -1
	   end
	end
	return -2`*/
	//优化
	stringLua := `if (redis.call('SADD',KEYS[2],ARGV[1])>0) then
   redis.call('EXPIRE',KEYS[2],ARGV[2])
   local diamond=redis.call('LPOP',KEYS[3])
   if diamond then
      return diamond
   else
      local names={'TotalQuantity'}
      local bulk=redis.call('HMGET',KEYS[1],unpack(names))
      redis.call('HSET',KEYS[1],'SendQuantity',tonumber(bulk[1])) 
      return -1
   end
end
return -2`
	hongBaoKey := generateHongBaoCacheKey(int32(hongBaoId))
	userCacheKey := generateHongBaoUserCacheKey(hongBaoId, userId)
	userDiamondKey := generateHongBaoDiamondCacheKey(int32(hongBaoId))
	return global2.GetRds().Eval(stringLua, []string{hongBaoKey, userCacheKey, userDiamondKey}, userId, _const.HONG_BAO_USER_GRAB_KEY_EXPIRED_TIME).Int()
}

/**
 * @Author admin
 * @Description //抢红包错误消息
 * @version: v1.8.0
 * @Date 10:42 2022/7/11
 * @Param
 * @return
 **/
func errMessage(message string) (*pb.GrabHongBaoResp, error) {
	global2.Log.Errorf("%s_%s", message, util.Convert2())
	return nil, fmt.Errorf("%s", message)
}

/**
 * @Author admin
 * @Description //生成红包回复消息
 * @version: v1.8.0
 * @Date 10:40 2022/7/11
 * @Param
 * @return
 **/
func retMessage(message string, grabDiamond int32) (*pb.GrabHongBaoResp, error) {
	hongBaoResp := &pb.GrabHongBaoResp{}
	hongBaoResp.Diamond = grabDiamond
	hongBaoResp.Message = message
	return hongBaoResp, nil
}

/**
 * @Author admin
 * @Description //查询未有领完的红包列表
 * @version: v1.8.0
 * @Date 10:40 2022/7/11
 * @Param
 * @return
 **/

func (s *Server) GetHongBaoList(ctx context.Context, ids *pb.GetHongBaoListReq) (*pb.ItemHongBaoReq, error) {
	list, err := db_main.GetHongBaoList(generateListParam(ids.Id), "create_time asc")
	if err != nil {
		return &pb.ItemHongBaoReq{}, fmt.Errorf("%s%s", util.Convert2(), err.Error())
	}
	return &pb.ItemHongBaoReq{HongBao: list}, nil
}

/**
 * @Author admin
 * @Description //未有领完的红包回退 事务处理
 * @version: v1.8.0
 * @Date 10:40 2022/7/11
 * @Param
 * @return
 **/
func commitBackHongBao(hongBao *pb.HongBaoReq) error {
	//事务开始
	session := global2.GetX().Begin()
	_, err := db_main.UpUserDiamond(hongBao.UserId, int(hongBao.TotalDiamond-hongBao.SendDiamond), session)
	if err != nil {
		session.Rollback()
		return fmt.Errorf("%s生成红包失败%s", util.Convert2(), err.Error())
	}
	diamondRow, err := db_main.UpdateBackHongBao(int(hongBao.Id), session)
	if err != nil {
		session.Rollback()
		return fmt.Errorf("%s更新克拉失败%s", util.Convert2(), err)
	}
	if diamondRow == 0 {
		session.Rollback()
		return fmt.Errorf("%s克拉不足%s", util.Convert2(), err)
	}
	//生成账变
	err = db_main.CreateFlow(session, int(hongBao.UserId), int(hongBao.TotalDiamond-hongBao.SendDiamond), _const.CoinDiamond)
	if err != nil {
		session.Rollback()
		return fmt.Errorf("%s更新账变失败%s", util.Convert2(), err)
	}
	if err := session.Commit().Error; err != nil {
		session.Rollback()
		return fmt.Errorf("%s 生成红包事务失败 %s", util.Convert2(), err.Error())
	}
	return nil
}

/**
 * @Author admin
 * @Description //创建查询条件
 * @version: v1.8.0
 * @Date 10:40 2022/7/11
 * @Param
 * @return
 **/
func generateBackListParam() string {
	return fmt.Sprintf("end_time<%d and is_done=0", time.Now().Unix())
}

/**
 * @Author admin
 * @Description //创建查询条件
 * @version: v1.8.0
 * @Date 10:40 2022/7/11
 * @Param
 * @return
 **/
func generateListParam(id string) string {
	m := make(map[string]interface{})
	m["isDone"] = 0
	duration, _ := time.ParseDuration(fmt.Sprintf("-%ds", _const.SEARCH_BEFORE_TIME))
	//红包开始时间是在创建时间之后延迟多少秒
	startTime := time.Now().In(time.Now().Location()).Add(duration).Format(time2.TIME_LAYOUT_FORMAT_1)
	str := fmt.Sprintf("create_time>='%s'", startTime)
	if len(id) > 0 {
		str = fmt.Sprintf("%s and id=%d", str, cast.ToInt(id))
	}
	return str
}

/**
 * @Author admin
 * @Description //生成一个红包model
 * @version: v1.8.0
 * @Date 10:39 2022/7/11
 * @Param
 * @return
 **/
func generateHongBao(provid *pb.ProvideHongBaoReq) *models_main.HongBao {
	//duration, _ := timehelper.ParseDuration(fmt.Sprintf("%ds", provid.DelayTime))
	//红包开始时间是在创建时间之后延迟多少秒
	//startTime := timehelper.Now().In(timehelper.Now().Location()).Add(duration)
	moment := time.Now().Unix()
	startTime := moment + int64(provid.DelayTime)
	//红包结束时间是在开始时间之后多少时间结束
	endTime := moment + int64(_const.HONGBAO_SHOW_TIME)

	hongBaoModel := &models_main.HongBao{
		UserId:        provid.UserId,
		TotalDiamond:  int(provid.TotalDiamond),
		TotalQuantity: int(provid.TotalQuantity),
		SendQuantity:  0,
		SendDiamond:   0,
		DelayTime:     int(provid.DelayTime),
		LiveId:        provid.LiveId,
		Attention:     int8(provid.Attention),
		CreateTime:    moment,
		StartTime:     startTime,
		EndTime:       endTime,

		IsDone: 0}
	return hongBaoModel
}

/**
 * @Author admin
 * @Description //生成红包提交到db 以及缓存中
 * @version: v1.8.0
 * @Date 18:11 2022/7/8
 * @Param
 * @return
 **/
func hongBaoCommit(hongBaoModel *models_main.HongBao, list []interface{}) (*pb.ProvideHongBaoResp, error) {
	//事务开始
	session := global2.GetX().Begin()
	err := db_main.InsertHongBAO(hongBaoModel, session)
	if err != nil {
		session.Rollback()
		return nil, fmt.Errorf("%s生成红包失败%s", util.Convert2(), err.Error())
	}
	diamondRow, err := db_main.UpUserDiamond(hongBaoModel.UserId, -hongBaoModel.TotalDiamond, session)
	if err != nil {
		session.Rollback()
		return nil, fmt.Errorf("%s更新克拉失败%s", util.Convert2(), err)
	}
	if diamondRow == 0 {
		session.Rollback()
		return nil, fmt.Errorf("%s克拉不足%s", util.Convert2(), err)
	}
	//生成账变
	err = db_main.CreateFlow(session, int(hongBaoModel.UserId), -hongBaoModel.TotalDiamond, _const.CoinDiamond)
	if err != nil {
		session.Rollback()
		return nil, fmt.Errorf("%s更新账变失败%s", util.Convert2(), err)
	}
	//红包存入到redis map序列
	if err := hongBaoSaveRedisMapCache(hongBaoModel); err != nil {
		session.Rollback()
		return nil, fmt.Errorf("%s 保存红包信息到redis失败 %s", util.Convert2(), err.Error())
	}
	if err := pushDiamondListToCache(hongBaoModel, list); err != nil {
		session.Rollback()
		return nil, fmt.Errorf("%s 保存红包List到redis失败 %s", util.Convert2(), err.Error())
	}
	//红包全写入缓存之后才写入数据库
	if err := session.Commit().Error; err != nil {
		return nil, fmt.Errorf("%s 生成红包事务失败 %s", util.Convert2(), err.Error())
	}
	p := &pb.ProvideHongBaoResp{Id: int32(hongBaoModel.Id), Message: "生成红包成功"}
	return p, nil
}

/**
 * @Author admin
 * @Description //生成一个克拉 Model
 * @version: v1.8.0
 * @Date 10:38 2022/7/11
 * @Param
 * @return
 **/
func generateDiamondModel(diamond int, hongBaoId int, userId int64) *models_main.Diamond {
	return &models_main.Diamond{
		GrabDiamond: diamond,
		HongBaoId:   hongBaoId,
		UserId:      userId,
	}
}

/**
 * @Author admin
 * @Description //单例模式从redis 中获取红包
 * @version: v1.8.0
 * @Date 10:37 2022/7/11
 * @Param
 * @return
 **/
func getOptimizedHongBao(hongBaoReq *pb.GrabHongBaoReq) (*models_main.HongBao, error) {
	//从redis中取红包
	hongBao, err := getHongBaoFromRedisMapCache(hongBaoReq)
	if err != nil {
		lock.Lock()
		defer lock.Unlock()
		//类似于单例模式中的双检 再次从redis中取红包
		hongBao, err = getHongBaoFromRedisMapCache(hongBaoReq)
		if err != nil {
			hongBao, err = getHongBaoFromDb(hongBaoReq.HongBaoId)
			if err != nil {
				return nil, fmt.Errorf("%s%s", util.Convert2(), err)
			}
			hongBaoSaveRedisMapCache(hongBao)
		}
	}
	return hongBao, nil
}

/**
 * @Author admin
 * @Description //缓存红包(map序列)
 * @version: v1.8.0
 * @Date 10:37 2022/7/11
 * @Param
 * @return
 **/
func hongBaoSaveRedisMapCache(hongBao *models_main.HongBao) error {
	keyId := generateHongBaoCacheKey(int32(hongBao.Id))
	hongBaoMap := structs.Map(hongBao)
	_, err := global2.GetRds().HMSet(keyId, hongBaoMap).Result()
	if err != nil {
		return err
	}
	_, err = global2.GetRds().Expire(keyId, time.Duration(_const.HONG_BAO_CACHE_EXPIRED_TIME)*time.Second).Result()
	if err != nil {
		return err
	}
	return nil
}

/**
 * @Author admin
 * @Description //从redis(map 序列) 中取一个红包信息
 * @version: v1.8.0
 * @Date 10:37 2022/7/11
 * @Param
 * @return
 **/
func getHongBaoFromRedisMapCache(hongBaoReq *pb.GrabHongBaoReq) (*models_main.HongBao, error) {
	keyId := generateHongBaoCacheKey(hongBaoReq.HongBaoId)
	hongBao := &models_main.HongBao{}
	names := structs.Names(hongBao)
	if result, err := global2.GetRds().HMGet(keyId, names...).Result(); err == nil {
		for ind, val := range result {
			if val != nil {
				switch names[ind] {
				case "Id":
					hongBao.Id = cast.ToInt(val)
				case "SenderUid":
					hongBao.UserId = cast.ToInt64(val)
				case "TotalDiamond":
					hongBao.TotalDiamond = cast.ToInt(val)
				case "SendDiamond":
					hongBao.SendDiamond = cast.ToInt(val)
				case "TotalQuantity":
					hongBao.TotalQuantity = cast.ToInt(val)
				case "SendQuantity":
					hongBao.SendQuantity = cast.ToInt(val)
				case "DelayTime":
					hongBao.DelayTime = cast.ToInt(val)
				case "LiveId":
					hongBao.LiveId = cast.ToInt64(val)
				case "Attention":
					hongBao.Attention = int8(cast.ToInt(val))
				case "CreateTime":
					hongBao.CreateTime = cast.ToInt64(val)
				case "StartTime":
					hongBao.StartTime = cast.ToInt64(val)
				case "EndTime":
					hongBao.EndTime = cast.ToInt64(val)
				case "IsDone":
					hongBao.IsDone = int8(cast.ToInt(val))
				}
			}
		}
	}
	return hongBao, nil
}

/**
 * @Author admin
 * @Description //生成redisKey
 * @version: v1.8.0
 * @Date 10:36 2022/7/11
 * @Param
 * @return
 **/
func generateHongBaoCacheKey(hongBaoId int32) string {
	return fmt.Sprintf("%s:%d", _const.HONG_BAO_CACHE_REDIS_KEY, hongBaoId)
}

/**
 * @Author admin
 * @Description //生成redisKey
 * @version: v1.8.0
 * @Date 10:36 2022/7/11
 * @Param
 * @return
 **/
func generateHongBaoDiamondCacheKey(hongBaoId int32) string {
	return fmt.Sprintf("%s:%d", _const.HONG_BAO_DIAMOND_CACHE_REDIS_KEY, hongBaoId)
}

/**
 * @Author admin
 * @Description //生成redisKey
 * @version: v1.8.0
 * @Date 10:36 2022/7/11
 * @Param
 * @return
 **/
func generateHongBaoUserCacheKey(hongBaoId, userId int) string {
	return fmt.Sprintf("%s:%d:%d", _const.HONG_BAO_USER_CACHE_REDIS_KEY, hongBaoId, getHongBaoUserKeySegmentNum(userId))
}

/**
 * @Author admin
 * @Description //生成redisKey
 * @version: v1.8.0
 * @Date 10:36 2022/7/11
 * @Param
 * @return
 **/
func getHongBaoUserKeySegmentNum(userId int) int {
	segment := global2.Config.GetInt("hongbao.segment")
	if segment > 0 {
		return userId % segment
	} else {
		return userId % 10
	}

}

/**
 * @Author admin
 * @Description //FIXME 有点漏洞
 * @version: v1.8.0
 * @Date 9:13 2022/7/8
 * @Param
 * @return
 **/
func grabRandomDiamond(hongBao *models_main.HongBao) int {
	remainSize := hongBao.TotalQuantity - hongBao.SendQuantity //剩余的红包数量
	diamond := hongBao.TotalDiamond - hongBao.SendDiamond      //剩余的克拉
	if remainSize == 1 {
		hongBao.SendQuantity = hongBao.TotalQuantity
		hongBao.SendDiamond = hongBao.TotalDiamond
		return diamond
	}
	rand.Seed(time.Now().UnixNano())
	min := _const.HONGBAO_LOW_PRICE
	surplus := (hongBao.TotalDiamond - hongBao.SendDiamond) / (hongBao.TotalQuantity - hongBao.SendQuantity)
	//剩下的金额平分红包金额不能小于红包最小金额
	max := surplus * 2
	diamond = int(rand.Float64() * float64(max))
	if diamond < min {
		diamond = min
	} else {
		//防止产生负数红包并且当产生完当前红包之后余额 足够余下的红包平均值不小于红包最小值
		surplus = (hongBao.TotalDiamond - hongBao.SendDiamond - diamond) / (hongBao.TotalQuantity - hongBao.SendQuantity - 1)
		if surplus < min {
			diamond = min
		}
	}
	hongBao.SendQuantity++
	hongBao.SendDiamond += diamond
	return diamond
}

/**
 * @Author admin
 * @Description 随机生成指定个数的红包
 * @version: v1.8.0
 * @Date 10:00 2022/7/8
 * @Param
 * @return
 **/
func getRandomDiamondList(hongBao *models_main.HongBao) []interface{} {
	diamondList := make([]interface{}, 0)
	for i := 0; i < hongBao.TotalQuantity; i++ {
		diamondList = append(diamondList, grabRandomDiamond(hongBao))
	}

	return diamondList
}

/**
 * @Author admin
 * @Description //切片打乱顺序
 * @version: v1.8.0
 * @Date 9:02 2022/7/12
 * @Param
 * @return
 **/
func Shuffle(slice []interface{}) {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	for len(slice) > 0 {
		n := len(slice)
		randIndex := r.Intn(n)
		slice[n-1], slice[randIndex] = slice[randIndex], slice[n-1]
		slice = slice[:n-1]
	}
}

/**
 * @Author admin
 * @Description //根据红包Id,查询红包信息
 * @version: v1.8.0
 * @Date 10:34 2022/7/11
 * @Param
 * @return
 **/
func getHongBaoFromDb(hongBaoId int32) (*models_main.HongBao, error) {
	return db_main.QueryById(hongBaoId)
}

/**
 * @Author admin
 * @Description //抢到的红包保存到db 使用失败并重试
 * @version: v1.8.0
 * @Date 10:33 2022/7/11
 * @Param
 * @return
 **/
func retryBatchSaveDiamondToDb(diamondList []*models_main.Diamond, retryTime int) error {
	for i := 0; i < retryTime; i++ {
		if err := retryBatchCommit(diamondList); err == nil {
			//事务提交成功退出
			return nil
		}
		//如果提交数据库失败(暂停时间*i)，然后再次提交数据
		time.Sleep(time.Millisecond * _const.HONG_BAO_COMMIT_FAIL_INTERVAL * time.Duration(i))
	}
	//在重试retryTime次后仍然失败，重新入队
	for _, diamond := range diamondList {
		diamondQueue <- diamond
	}
	return fmt.Errorf("%s 重试 %d多少次仍然失败", util.Convert2(), _const.RETRY_TIME)
}

/**
 * @Author admin
 * @Description //批量提交事务处理
 * @version: v1.8.0
 * @Date 18:13 2022/7/7
 * @Param
 * @return
 **/
func retryBatchCommit(diamondList []*models_main.Diamond) error {
	session := global2.GetX().Begin()
	//删除临时表
	if err := db_main.DropDiamondTemp(session); err != nil {
		return retryCommitMsg(session)
	}
	//批量插入到临时表中
	if num, _ := db_main.CreateDiamondTemp(session, diamondList); num == 0 {
		return retryCommitMsg(session)
	}
	//从临时表中找到数据并更新红包状态
	if bao, _ := db_main.BatchUpdateHongBao(session); bao == 0 {
		return retryCommitMsg(session)
	}
	//批量更新用户 diamond
	if userDiamond, _ := db_main.BatchUpdateUserDiamond(session); userDiamond == 0 {
		return retryCommitMsg(session)
	}
	//批量更新用户 生成账变
	if err := db_main.BatchFlowHongBao(session); err != nil {
		return retryCommitMsg(session)
	}
	//提交事务
	if err := session.Commit().Error; err != nil {
		return retryCommitMsg(session)
	}
	return nil
}

/**
 * @Author admin
 * @Description //提交数据失败,消息处理
 * @version: v1.8.0
 * @Date 10:34 2022/7/11
 * @Param
 * @return
 **/
func retryCommitMsg(session *gorm.DB) error {
	session.Rollback()
	time.Sleep(time.Duration(_const.RETRY_TIME_SLEEP) * time.Millisecond)
	return errors.New("提交数据库异常,请重试")
}

/**
 * @Author admin
 * @Description //把红包保存到缓存中
 * @version: v1.8.0
 * @Date 10:38 2022/7/8
 * @Param
 * @return
 **/
func pushDiamondListToCache(hongBaoModel *models_main.HongBao, list []interface{}) error {
	key := generateHongBaoDiamondCacheKey(int32(hongBaoModel.Id))
	_, err := global2.GetRds().LPush(key, list...).Result()
	if err != nil {
		return err
	}
	_, err = global2.GetRds().Expire(key, time.Duration(_const.HONG_BAO_CACHE_EXPIRED_TIME)*time.Second).Result()
	if err != nil {
		return err
	}
	return nil
}
